package cn.innosmart.aq.manager;

import android.text.TextUtils;

import com.tutk.p2p.ConnectionEntity;
import com.tutk.p2p.ResponseHandler;

import org.json.JSONArray;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import cn.innosmart.aq.bean.AlarmConditionBean;
import cn.innosmart.aq.bean.AquariumBean;
import cn.innosmart.aq.bean.DeviceBean;
import cn.innosmart.aq.bean.RuleBean;
import cn.innosmart.aq.bean.TriggerBean;
import cn.innosmart.aq.bean.ValueConditionBean;
import cn.innosmart.aq.util.DeviceConstant;
import cn.innosmart.aq.util.SystemConstant;

/**
 * Created by David on 2015/7/1.
 */
public class RuleManager extends BaseManager {
    private static AddCallBack addCallBack;
    private static UpdateCallBack updateCallBack;
    private static RemoveCallBack removeCallBack;
    private static EnableCallBack enableCallBack;
    private static DisableCallBack disableCallBack;
    private static ListCallBack listCallBack;
    private String Tag = "RuleManager";
    //{"code":0,"message":"Success","result":{"id":"SN0513_xfGX7uNleZ5ZqGShLSHh"},"type":"resp","callid":1439888740043,"method":"RuleManager.Add"}
    private ResponseHandler.ResponseCallback mRuleManagerAddCallBack = new ResponseHandler.ResponseCallback() {
        @Override
        public void onResponseCallback(ConnectionEntity connectionEntity, String message) {
            log(Tag, "RuleManager.Add get response=" + message);
            JSONObject jRoot = null;
            try {
                jRoot = new JSONObject(message);
                int rspCode = jRoot.getInt("code");
                String rspMsg = jRoot.getString("message");
                if (0 == rspCode && "Success".equals(rspMsg)) {
                    String id = jRoot.getJSONObject("result").getString("id");
                    if (addCallBack != null) {
                        addCallBack.onAddResponseCallBack(0, id);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    };
    private ResponseHandler.ResponseCallback mRuleManagerUpdateCallBack = new ResponseHandler.ResponseCallback() {
        @Override
        public void onResponseCallback(ConnectionEntity connectionEntity, String message) {
            log(Tag, "RuleManager.Update get response=" + message);
            JSONObject jRoot = null;
            try {
                jRoot = new JSONObject(message);
                int rspCode = jRoot.getInt("code");
                String rspMsg = jRoot.getString("message");
                if (0 == rspCode && "Success".equals(rspMsg)) {
                    String id = jRoot.getJSONObject("result").getString("id");
                    if (updateCallBack != null) {
                        updateCallBack.onUpdateResponseCallBack(0, id);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    };
    private ResponseHandler.ResponseCallback mRuleManagerRemoveCallBack = new ResponseHandler.ResponseCallback() {
        @Override
        public void onResponseCallback(ConnectionEntity connectionEntity, String message) {
            log(Tag, "RuleManager.Remove get response=" + message);
            JSONObject jRoot = null;
            try {
                jRoot = new JSONObject(message);
                int rspCode = jRoot.getInt("code");
                String rspMsg = jRoot.getString("message");
                if (0 == rspCode && "Success".equals(rspMsg)) {
                    if (removeCallBack != null) {
                        removeCallBack.onRemoveResponseCallBack(0, null);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    };
    private ResponseHandler.ResponseCallback mRuleManagerEnableCallBack = new ResponseHandler.ResponseCallback() {
        @Override
        public void onResponseCallback(ConnectionEntity connectionEntity, String message) {
            log(Tag, "RuleManager.Enable get response=" + message);
            JSONObject jRoot = null;
            try {
                jRoot = new JSONObject(message);
                int rspCode = jRoot.getInt("code");
                String rspMsg = jRoot.getString("message");
                if (0 == rspCode && "Success".equals(rspMsg)) {
                    if (enableCallBack != null) {
                        enableCallBack.onEnableResponseCallBack(0, null);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    };
    private ResponseHandler.ResponseCallback mRuleManagerDisableCallBack = new ResponseHandler.ResponseCallback() {
        @Override
        public void onResponseCallback(ConnectionEntity connectionEntity, String message) {
            log(Tag, "RuleManager.Disable get response=" + message);
            JSONObject jRoot = null;
            try {
                jRoot = new JSONObject(message);
                int rspCode = jRoot.getInt("code");
                String rspMsg = jRoot.getString("message");
                if (0 == rspCode && "Success".equals(rspMsg)) {
                    if (disableCallBack != null) {
                        disableCallBack.onDisableResponseCallBack(0, null);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    };
    private ResponseHandler.ResponseCallback mRuleManagerExecuteCallBack = new ResponseHandler.ResponseCallback() {
        @Override
        public void onResponseCallback(ConnectionEntity connectionEntity, String message) {
            log(Tag, "RuleManager.Execute get response=" + message);

        }
    };
    private ResponseHandler.ResponseCallback mRuleManagerListCallBack = new ResponseHandler.ResponseCallback() {
        @Override
        public void onResponseCallback(ConnectionEntity connectionEntity, String message) {
            log(Tag, "RuleManager.List get response=" + message);
            connectionEntity.flags.remove(connectionEntity.RULELIST);
            JSONObject jRoot = null;
            ArrayList<Object> ruleList;
            try {
                jRoot = new JSONObject(message);
                ruleList = new ArrayList<Object>();
                int rspCode = jRoot.getInt("code");
                String rspMsg = jRoot.getString("message");
                if (0 == rspCode && "Success".equals(rspMsg)) {
                    JSONArray jsonArray = jRoot.getJSONObject("result").getJSONArray("rules");
                    for (int i = 0; i < SystemConstant.aquariumList.size(); i++) {
                        SystemConstant.aquariumList.get(i).getRuleList().clear();
                    }
                    if (SystemConstant.conditionRuleList == null)
                        SystemConstant.conditionRuleList = new ArrayList<>();
                    if (DeviceConstant.alarmConditionBeanHashMap == null) {
                        DeviceConstant.alarmConditionBeanHashMap = new HashMap<String, AlarmConditionBean>();
                    } else {
                        DeviceConstant.alarmConditionBeanHashMap.clear();
                    }

                    //在这里区分规则应该是在实时界面还是Rule界面
                    for (int i = 0; i < jsonArray.length(); i++) {
                        RuleBean ruleBean = new RuleBean((JSONObject) jsonArray.getJSONObject(i));
                        //根据USerTAG判断是不是区间报警条件
                        if (!TextUtils.isEmpty(ruleBean.getUserTag())) {
                            //是区间报警
                            String address = ruleBean.getUserTag();
                            if(address.contains("/37/")) {
                                String slist[] = address.split("\\/");
                                String wattDeviceBeanAddress = slist[0] + "//" + slist[2] + "/" + slist[3] + "/" + 50 + "/" + slist[5] + "/" + 2; // zwave://e5a00bee/3/50/3/2
                                address = wattDeviceBeanAddress;
                            }
                            AlarmConditionBean alarmConditionBean = DeviceConstant.alarmConditionBeanHashMap.get(address);
                            //存入区间报警列表
                            if (alarmConditionBean == null) {
                                alarmConditionBean = new AlarmConditionBean();
                                DeviceConstant.alarmConditionBeanHashMap.put(address, alarmConditionBean);
                            }
                            //判断当前设备的状态是否处于异常值
                            DeviceBean deviceBean = SystemConstant.deviceBeanHashMap.get(address);
                            alarmConditionBean.setEnable(ruleBean.getEnabled());
                            Iterator iter = ruleBean.getTriggers().entrySet().iterator();
                            TriggerBean triggerBean = null;
                            while (iter.hasNext()) {
                                Map.Entry entry = (Map.Entry) iter.next();
                                triggerBean = (TriggerBean) entry.getValue();
                            }
                            ValueConditionBean valueConditionBean = triggerBean.getValueConditionBeans().get(0);
                            if (valueConditionBean.getOp().equals(">")) {
                                alarmConditionBean.setBelowValue(valueConditionBean.getThreshold());
                                if (deviceBean != null) {
                                    if (deviceBean.getSensorvalue() > valueConditionBean.getThreshold()) {
                                        deviceBean.setAlarm(true);
                                    } else {
                                        deviceBean.setAlarm(false);
                                    }
                                }
                            }
                            if (valueConditionBean.getOp().equals("<")) {
                                alarmConditionBean.setAboveValue(valueConditionBean.getThreshold());
                                if (deviceBean != null) {
                                    if (deviceBean.getSensorvalue() < valueConditionBean.getThreshold()) {
                                        deviceBean.setAlarm(true);
                                    } else {
                                        deviceBean.setAlarm(false);
                                    }
                                }
                            }
                            if (valueConditionBean.getOp().equals("notin")) {
                                JSONArray jsonValues = valueConditionBean.getThresholdList();
                                double below = jsonValues.getDouble(1);
                                double above = jsonValues.getDouble(0);
                                alarmConditionBean.setBelowValue(below);
                                alarmConditionBean.setAboveValue(above);
                                if (deviceBean != null) {
                                    if (deviceBean.getSensorvalue() > below) {
                                        deviceBean.setAlarm(true);
                                    }
                                    if (deviceBean.getSensorvalue() < above) {
                                        deviceBean.setAlarm(true);
                                    }
                                }
                            }
                            SystemConstant.conditionRuleList.add(ruleBean);
                        } else {
                            //正常初始化为规则，并存入内存
                            ruleList.add(ruleBean);
                            String place = ruleBean.getPlace();
                            if (!TextUtils.isEmpty(place)) {
                                AquariumBean aquariumBean = AquariumBean.findAquariumById(place);
                                aquariumBean.getRuleList().add(ruleBean);
                                System.out.println("add " + ruleBean.getTitle() + " into " + place);
                            }
                        }
                    }
                    if (listCallBack != null) {
                        listCallBack.onListResponseCallBack(0, ruleList);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    };
    private ResponseHandler.ResponseCallback mRuleManagerGetAlarmCallBack = new ResponseHandler.ResponseCallback() {
        @Override
        public void onResponseCallback(ConnectionEntity connectionEntity, String message) {
            log(Tag, "RuleManager.GetAlarm get response=" + message);

        }
    };
    private ResponseHandler.ResponseCallback mRuleManagerUpdateAlarmCallBack = new ResponseHandler.ResponseCallback() {
        @Override
        public void onResponseCallback(ConnectionEntity connectionEntity, String message) {
            log(Tag, "RuleManager.UpdateAlarm get response=" + message);

        }
    };
    private ResponseHandler.ResponseCallback mRuleManagerArmSystemCallBack = new ResponseHandler.ResponseCallback() {
        @Override
        public void onResponseCallback(ConnectionEntity connectionEntity, String message) {
            log(Tag, "RuleManager.ArmSystem get response=" + message);

        }
    };
    private ResponseHandler.ResponseCallback mRuleManagerDisarmSystemCallBack = new ResponseHandler.ResponseCallback() {
        @Override
        public void onResponseCallback(ConnectionEntity connectionEntity, String message) {
            log(Tag, "RuleManager.DisarmSystem get response=" + message);

        }
    };

    private RuleManager() {
    }

    public static RuleManager getInstance() {
        return RuleManagerInstance.instance;
    }

    //{"code":0,"message":"Success","result":{"id":"SN0513_xfGX7uNleZ5ZqGShLSHh"},"type":"resp","callid":1439888740043,"method":"RuleManager.Add"}
    // RuleManager.Add
    public boolean Add(ConnectionEntity connectionEntity, String params, AddCallBack addCallBack) {
        log(Tag, "Register. UID = " + connectionEntity.getUid() + ", params = " + params);
        this.addCallBack = addCallBack;
        ResponseHandler handler = new ResponseHandler();
        long callid = System.currentTimeMillis() / 1000;
        handler.setCallback(mRuleManagerAddCallBack);
        connectionEntity.mReqRspHashMap.put(callid, handler);
        if (!SendCommand(connectionEntity, connectionEntity.getUid(), "RuleManager.Add", params, callid)) {
            connectionEntity.mReqRspHashMap.remove(callid);
            return false;
        } else {
            return true;
        }
    }

    // RuleManager.Update
    public boolean Update(ConnectionEntity connectionEntity, String params, UpdateCallBack updateCallBack) {
        log(Tag, "Update. UID = " + connectionEntity.getUid() + ", params = " + params);
        this.updateCallBack = updateCallBack;
        ResponseHandler handler = new ResponseHandler();
        long callid = System.currentTimeMillis();
        handler.setCallback(mRuleManagerUpdateCallBack);
        connectionEntity.mReqRspHashMap.put(callid, handler);
        if (!SendCommand(connectionEntity, connectionEntity.getUid(), "RuleManager.Update", params, callid)) {
            connectionEntity.mReqRspHashMap.remove(callid);
            return false;
        } else {
            return true;
        }
    }

    // RuleManager.Update
    public boolean Update(ConnectionEntity connectionEntity, String params) {
        log(Tag, "Update. UID = " + connectionEntity.getUid() + ", params = " + params);
        ResponseHandler handler = new ResponseHandler();
        long callid = System.currentTimeMillis();
        handler.setCallback(mRuleManagerUpdateCallBack);
        connectionEntity.mReqRspHashMap.put(callid, handler);
        if (!SendCommand(connectionEntity, connectionEntity.getUid(), "RuleManager.Update", params, callid)) {
            connectionEntity.mReqRspHashMap.remove(callid);
            return false;
        } else {
            return true;
        }
    }

    // RuleManager.Remove
    public boolean Remove(ConnectionEntity connectionEntity, String params, RemoveCallBack removeCallBack) {
        log(Tag, "Remove. UID = " + connectionEntity.getUid() + ", params = " + params);
        this.removeCallBack = removeCallBack;
        long callid = System.currentTimeMillis() / 1000;
        ResponseHandler handler = new ResponseHandler();
        handler.setCallback(mRuleManagerRemoveCallBack);
        connectionEntity.mReqRspHashMap.put(callid, handler);
        if (!SendCommand(connectionEntity, connectionEntity.getUid(), "RuleManager.Remove", params, callid)) {
            connectionEntity.mReqRspHashMap.remove(callid);
            return false;
        } else {
            return true;
        }
    }

    // RuleManager.Enable
    public boolean Enable(ConnectionEntity connectionEntity, JSONObject params, EnableCallBack enableCallBack) {
        log(Tag, "Enable. UID = " + connectionEntity.getUid() + ", params = " + params);
        this.enableCallBack = enableCallBack;
        long callid = System.currentTimeMillis();
        ResponseHandler handler = new ResponseHandler();
        handler.setCallback(mRuleManagerEnableCallBack);
        connectionEntity.mReqRspHashMap.put(callid, handler);
        if (!SendCommand(connectionEntity, connectionEntity.getUid(), "RuleManager.Enable", params.toString(), callid)) {
            connectionEntity.mReqRspHashMap.remove(callid);
            return false;
        } else {
            return true;
        }

    }

    // RuleManager.Disable
    public boolean Disable(ConnectionEntity connectionEntity, JSONObject params, DisableCallBack disableCallBack) {
        log(Tag, "Disable. UID = " + connectionEntity.getUid() + ", params = " + params);
        this.disableCallBack = disableCallBack;
        long callid = System.currentTimeMillis();
        ResponseHandler handler = new ResponseHandler();
        handler.setCallback(mRuleManagerDisableCallBack);
        connectionEntity.mReqRspHashMap.put(callid, handler);
        if (!SendCommand(connectionEntity, connectionEntity.getUid(), "RuleManager.Disable", params.toString(), callid)) {
            connectionEntity.mReqRspHashMap.remove(callid);
            return false;
        } else {
            return true;
        }
    }

    // RuleManager.Execute
    public boolean Execute(ConnectionEntity connectionEntity, HashMap<Long, ResponseHandler> mReqRspHashMap, String UID, String params, long callid) {
        log(Tag, "Execute. UID = " + UID + ", params = " + params);
        ResponseHandler handler = new ResponseHandler();
        handler.setCallback(mRuleManagerExecuteCallBack);
        mReqRspHashMap.put(callid, handler);
        if (!SendCommand(connectionEntity, UID, "RuleManager.Execute", params, callid)) {
            mReqRspHashMap.remove(callid);
            return false;
        } else {
            return true;
        }
    }

    // RuleManager.List
    public boolean List(ConnectionEntity connectionEntity, ListCallBack callBack) {
        log(Tag, "List. UID = " + connectionEntity.getUid());
        connectionEntity.flags.add(connectionEntity.RULELIST);
        this.listCallBack = callBack;
        long callid = System.currentTimeMillis() / 1000;
        JSONObject jParams = new JSONObject();
        ResponseHandler handler = new ResponseHandler();
        handler.setCallback(mRuleManagerListCallBack);
        connectionEntity.mReqRspHashMap.put(callid, handler);
        if (!SendCommand(connectionEntity, connectionEntity.getUid(), "RuleManager.List", jParams.toString(), callid)) {
            connectionEntity.mReqRspHashMap.remove(callid);
            return false;
        } else {
            return true;
        }
    }

    // RuleManager.List
    public boolean List(ConnectionEntity connectionEntity, ListCallBack callBack, int delay) {
        log(Tag, "List. UID = " + connectionEntity.getUid());
        connectionEntity.flags.add(connectionEntity.RULELIST);
        this.listCallBack = callBack;
        long callid = System.currentTimeMillis() / 1000;
        if (delay != 0) {
            callid = callid + delay;
        }
        JSONObject jParams = new JSONObject();
        ResponseHandler handler = new ResponseHandler();
        handler.setCallback(mRuleManagerListCallBack);
        connectionEntity.mReqRspHashMap.put(callid, handler);
        if (!SendCommand(connectionEntity, connectionEntity.getUid(), "RuleManager.List", jParams.toString(), callid)) {
            connectionEntity.mReqRspHashMap.remove(callid);
            return false;
        } else {
            return true;
        }
    }

    // RuleManager.GetAlarm
    public boolean GetAlarm(ConnectionEntity connectionEntity, HashMap<Long, ResponseHandler> mReqRspHashMap, String UID, long callid) {
        log(Tag, "GetAlarm. UID = " + UID);
        ResponseHandler handler = new ResponseHandler();
        handler.setCallback(mRuleManagerGetAlarmCallBack);
        mReqRspHashMap.put(callid, handler);
        if (!SendCommand(connectionEntity, UID, "RuleManager.GetAlarm", "{}", callid)) {
            mReqRspHashMap.remove(callid);
            return false;
        } else {
            return true;
        }
    }

    // RuleManager.UpdateAlarm
    public boolean UpdateAlarm(ConnectionEntity connectionEntity, HashMap<Long, ResponseHandler> mReqRspHashMap, String UID, String params, long callid) {
        log(Tag, "UpdateAlarm. UID = " + UID + ", params = " + params);
        ResponseHandler handler = new ResponseHandler();
        handler.setCallback(mRuleManagerUpdateAlarmCallBack);
        mReqRspHashMap.put(callid, handler);
        if (!SendCommand(connectionEntity, UID, "RuleManager.UpdateAlarm", params, callid)) {
            mReqRspHashMap.remove(callid);
            return false;
        } else {
            return true;
        }
    }

    // RuleManager.ArmSystem
    public boolean ArmSystem(ConnectionEntity connectionEntity, HashMap<Long, ResponseHandler> mReqRspHashMap, String UID, long callid) {
        log(Tag, "ArmSystem. UID = " + UID);
        ResponseHandler handler = new ResponseHandler();
        handler.setCallback(mRuleManagerUpdateAlarmCallBack);
        mReqRspHashMap.put(callid, handler);
        if (!SendCommand(connectionEntity, UID, "RuleManager.ArmSystem", "{}", callid)) {
            mReqRspHashMap.remove(callid);
            return false;
        } else {
            return true;
        }
    }

    // RuleManager.DisarmSystem
    public boolean DisarmSystem(ConnectionEntity connectionEntity, HashMap<Long, ResponseHandler> mReqRspHashMap, String UID, long callid) {
        log(Tag, "DisarmSystem. UID = " + UID);
        ResponseHandler handler = new ResponseHandler();
        handler.setCallback(mRuleManagerDisarmSystemCallBack);
        mReqRspHashMap.put(callid, handler);
        if (!SendCommand(connectionEntity, UID, "RuleManager.DisarmSystem", "{}", callid)) {
            mReqRspHashMap.remove(callid);
            return false;
        } else {
            return true;
        }
    }

    public interface AddCallBack {
        void onAddResponseCallBack(int ret, String ruleid);
    }

    public interface UpdateCallBack {
        void onUpdateResponseCallBack(int ret, String ruleid);
    }

    public interface RemoveCallBack {
        void onRemoveResponseCallBack(int ret, String ruleid);
    }

    public interface EnableCallBack {
        void onEnableResponseCallBack(int ret, String ruleid);
    }

    public interface DisableCallBack {
        void onDisableResponseCallBack(int ret, String ruleid);
    }

    public interface ListCallBack {
        void onListResponseCallBack(int ret, ArrayList<Object> childList);
    }

    private static class RuleManagerInstance {
        private static final RuleManager instance = new RuleManager();
    }
}
